package com.caption.core.annotations;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.caption.core.model.entity.BaseData;
import com.caption.core.model.enums.BaseResultEnum;
import com.caption.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;


/**
 * 防重提交
 *
 * @author sunsa
 * @date 2022/1/17 10:50
 */
@Slf4j
@Aspect
@Component
public class RepeatCommitAdvice {
    /**
     * 切入点匹配所有注解为 RepeatCommit
     */
    @Autowired
    private RedisUtils redisUtils;

    @Pointcut("@annotation(com.caption.core.annotations.RepeatCommit)")
    public void repeatCommitPointcut() {
    }

    @Around(value = "repeatCommitPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        RepeatCommit repeatCommit = method.getAnnotation(RepeatCommit.class);
        String methodName = signature.getName();
        Object[] argList = pjp.getArgs();
        StringBuilder stringBuilder = new StringBuilder();
        for (Object arg : argList) {
            stringBuilder.append(JSONUtil.toJsonStr(arg));
        }
        String parma = SecureUtil.md5(stringBuilder.toString());
        //清空stringBuilder
        stringBuilder.delete(0, stringBuilder.length());
        String key = stringBuilder.append(repeatCommit.value())
                .append(methodName)
                .append(":")
                .append(parma)
                .toString();
        log.info("进入环绕方法参数:{}", key);
        //重复调用
        if (redisUtils.hashKey(key)) {
            BaseData data = new BaseData();
            data.setData(BaseResultEnum.CALL_REPEAT.getCode());
            data.setMessage(BaseResultEnum.CALL_REPEAT.getDesc());
            return data;
        }
        Object object = pjp.proceed();
        redisUtils.set(key, "1", repeatCommit.timeout(), repeatCommit.timeUnit());
        log.info("进入环绕方法返回值{}", JSON.toJSONString(object));
        return object;
    }


}
